package com.dxy.shardingjdbc.algorithm;

import com.alibaba.fastjson.JSON;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;
import java.util.zip.CRC32;

/**
 * @Description 订单编号分片算法
 * string的hashcode方法在一致性hash算法中实用价值较低，因为遇到连续的key时hash结果比较集中，做不到均衡
 * 这里使用CRC32做哈希
 * @Author dangxianyue
 * @Date 2023/2/6 16:30
 */
public class OrderSubTablePreciseAlgorithm implements PreciseShardingAlgorithm<String> {

    /**
     * 表拆分的具体算法
     * @param availableTargetNames 所有的分片集 由于我这个算法是指定了分表算法，则这里是物理表名列表，t_order_0、t_order_1、t_order_2、t_order_3
     * @param shardingValue 分片键的值
     * @return 返回物理表名称，如 t_order_1
     */
    @Override
    public String doSharding(Collection<String> availableTargetNames, PreciseShardingValue<String> shardingValue) {
        System.out.println("availableTargetNames: " + JSON.toJSONString(availableTargetNames) + "\nshardingValue: " + JSON.toJSONString(shardingValue));
        //availableTargetNames: ["t_order_0","t_order_1","t_order_2","t_order_3"]
        //shardingValue: {"columnName":"order_sn","logicTableName":"t_order","value":"SB230206619743989236"}
        return shardingValue.getLogicTableName() + "_" + getTableSuffix(availableTargetNames, shardingValue.getValue());
    }

    /**
     * 获取表的后缀，0、1、2、3
     */
    private long getTableSuffix(Collection<String> availableTargetNames, String orderSn) {
        CRC32 crc32 = new CRC32();
        crc32.update(orderSn.getBytes());
        return crc32.getValue() % availableTargetNames.size();
    }

}
